#pragma once

int Add(int x, int y);
int Sub(int x, int y);

//////////////////////////////////////////////////////////////////////////

enum {
    V_IN,
    V_OUT
};

enum class EnumClass {
    YES, NO,
};

//////////////////////////////////////////////////////////////////////////

class Unknown {
public:
    void Hello();
};

//////////////////////////////////////////////////////////////////////////

template <typename T>
struct T_Class {
    T m;
};

template <typename T>
T T_Func(const T &t) {
    return t;
}

typedef T_Class<int> T_int;

int Why(T_int ti)
#ifdef __CASTXML__
{
    return ti.m;
}
#else
;
#endif

//////////////////////////////////////////////////////////////////////////

struct K {
    enum KK {
        KK_1,
        KK_2,
        KK_3
    };

    virtual void KKK(const KK &kk = KK_2) const;

protected:

    enum E {
        E1
    };

    enum struct ES {
        VAL = 12345,
    };

    void KP() {}
    static void KPS() {}
};

struct K2 final : public K {
    virtual void KKK(const KK &kk = KK_2) const override;
};

struct K3 : public K {
    virtual void KKK(const KK &kk = KK_2) const final;
};

//////////////////////////////////////////////////////////////////////////

struct Dummy : public K {
    Dummy() {}

    int x, y, z;
    static void Register();
    static void KPS() {}
};

//////////////////////////////////////////////////////////////////////////

class PrivateCDtors {
public:

    static PrivateCDtors &GetInstance();

private:

    PrivateCDtors() {}
    ~PrivateCDtors() {}

    static PrivateCDtors ms_pcd;
};

//////////////////////////////////////////////////////////////////////////

template <typename T>
class A {
public:
    A(T t) : _t(t) {}
private:
    T _t;
};

extern template class A<int>; // explicit instantiation

//////////////////////////////////////////////////////////////////////////

struct CXXHeld {
    virtual void foo() const;
};

struct CXXHeld2 : public CXXHeld {};

struct ObjHolder {
    ObjHolder(CXXHeld *obj) : obj(obj) {}
    ~ObjHolder();
    void foo() const;

    CXXHeld *obj;
};
